package wili.b1.impl;

import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

public class ResultSetMetaDataObj implements ResultSetMetaData {
	final int columnCount;
	Col[] cc;
	ResultSetMetaData meta;
	final Map<String, Integer> nameToInd = new HashMap<>();

	static class Col {
		public int ind, type, columnDisplaySize;
		public int isNullable;
		public String typeName;
		public String name, label, tableName, schemaName;
		public boolean isAutoIncrement;
		private Map<String, Object> valueMap = new HashMap<>();

		public <T> T valueOf(String att) {
			Object ret = valueMap.get(att);
			return (T) ret;
		}

		public Col(ResultSetMetaData md, int ind) {
			this.ind = ind;

			try {
				this.type = md.getColumnType(ind);

				this.typeName = md.getColumnTypeName(ind);
				this.label = md.getColumnLabel(ind);
				this.name = md.getColumnName(ind);
				this.tableName = md.getTableName(ind);
				//
				this.isAutoIncrement = md.isAutoIncrement(ind);
				this.schemaName = md.getSchemaName(ind);
				this.isNullable = md.isNullable(ind);
				this.columnDisplaySize = md.getColumnDisplaySize(ind);
				//
				valueMap.put("getColumnClassName", md.getColumnClassName(ind));
				valueMap.put("getColumnDisplaySize", md.getColumnDisplaySize(ind));
				valueMap.put("getColumnLabel", md.getColumnLabel(ind));
				valueMap.put("getColumnName", md.getColumnName(ind));
				valueMap.put("getColumnType", md.getColumnType(ind));
				valueMap.put("getPrecision", md.getPrecision(ind));
				valueMap.put("getSchemaName", md.getSchemaName(ind));
				valueMap.put("getTableName", md.getTableName(ind));
				valueMap.put("isAutoIncrement", md.isAutoIncrement(ind));
				valueMap.put("isCaseSensitive", md.isCaseSensitive(ind));
				valueMap.put("isCurrency", md.isCurrency(ind));
				valueMap.put("isDefinitelyWritable", md.isDefinitelyWritable(ind));
				valueMap.put("isNullable", md.isNullable(ind));
				valueMap.put("isReadOnly", md.isReadOnly(ind));
				valueMap.put("isSearchable", md.isSearchable(ind));
				valueMap.put("isSigned", md.isSigned(ind));
				valueMap.put("isWritable", md.isWritable(ind));

			} catch (SQLException e) {
				throw new RuntimeException(e);
			}
		}
	}

	public ResultSetMetaDataObj(ResultSetMetaData md) {
		try {
			this.meta = md;
			this.columnCount = md.getColumnCount();
			this.cc = new Col[columnCount];
			for (int i = 0; i < columnCount; i++) {
				cc[i] = new Col(md, i + 1);
				nameToInd.put(cc[i].name, i);
			}

		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public int getColumnCount() throws SQLException {
		return columnCount;
	}

	@Override
	public boolean isAutoIncrement(int column) throws SQLException {
		return cc[column - 1].isAutoIncrement;
	}

	@Override
	public boolean isCaseSensitive(int column) throws SQLException {
		return cc[column - 1].valueOf("isCaseSensitive");
	}

	@Override
	public boolean isSearchable(int column) throws SQLException {
		return cc[column - 1].valueOf("isSearchable");
	}

	@Override
	public boolean isCurrency(int column) throws SQLException {
		return cc[column - 1].valueOf("isCurrency");
	}

	@Override
	public int isNullable(int column) throws SQLException {
		return cc[column - 1].valueOf("isNullable");
	}

	@Override
	public boolean isSigned(int column) throws SQLException {
		return cc[column - 1].valueOf("isSigned");
	}

	@Override
	public int getColumnDisplaySize(int column) throws SQLException {
		return cc[column - 1].columnDisplaySize;
	}

	@Override
	public String getColumnLabel(int column) throws SQLException {
		return cc[column - 1].label;
	}

	@Override
	public String getColumnName(int column) throws SQLException {
		return cc[column - 1].name;
	}

	@Override
	public String getSchemaName(int column) throws SQLException {
		return cc[column - 1].schemaName;
	}

	@Override
	public int getPrecision(int column) throws SQLException {
		return cc[column - 1].valueOf("getPrecision");
	}

	@Override
	public int getScale(int column) throws SQLException {
		return cc[column - 1].valueOf("getScale");
	}

	@Override
	public String getTableName(int column) throws SQLException {
		return cc[column - 1].tableName;
	}

	@Override
	public String getCatalogName(int column) throws SQLException {
		return cc[column - 1].valueOf("getCatalogName");
	}

	@Override
	public int getColumnType(int column) throws SQLException {
		return cc[column - 1].type;
	}

	@Override
	public String getColumnTypeName(int column) throws SQLException {
		return cc[column - 1].typeName;
	}

	@Override
	public boolean isReadOnly(int column) throws SQLException {
		return cc[column - 1].valueOf("isReadOnly");
	}

	@Override
	public boolean isWritable(int column) throws SQLException {
		return cc[column - 1].valueOf("isWritable");
	}

	@Override
	public boolean isDefinitelyWritable(int column) throws SQLException {
		return cc[column - 1].valueOf("isDefinitelyWritable");
	}

	@Override
	public String getColumnClassName(int column) throws SQLException {
		return cc[column - 1].valueOf("getColumnClassName");
	}

	@Override
	public <T> T unwrap(Class<T> iface) throws SQLException {
		throw new RuntimeException("unwrap");
	}

	@Override
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		throw new RuntimeException("todo_ResultSetMetaDataObj");
	}
}
